from flask import request, jsonify, current_app
from flask_login import login_required
from app import db
from app.models import SystemSetting, User
from app.admin import bp
from app.utils.decorators import admin_required

@bp.route('/settings', methods=['GET'])
@login_required
@admin_required
def get_settings():
    settings = SystemSetting.query.all()
    # Add default settings from config if not in DB, for display purposes
    # These won't be saved unless explicitly set via POST/PUT
    current_settings = {s.key: s.value for s in settings}
    
    all_settings_keys = ['llm_model', 'openai_api_key_admin', 'openai_api_base_admin', 'system_prompt']
    
    display_settings = {}
    for key in all_settings_keys:
        if key in current_settings:
            display_settings[key] = current_settings[key]
        elif key == 'llm_model':
            display_settings[key] = current_app.config.get('DEFAULT_LLM_MODEL')
        elif key == 'openai_api_key_admin': # Display only if set, or a placeholder for security
            display_settings[key] = "********" if current_app.config.get('OPENAI_API_KEY') else "Not Set (Using App Config)"
        elif key == 'openai_api_base_admin':
            display_settings[key] = current_app.config.get('OPENAI_API_BASE')
        elif key == 'system_prompt':
            display_settings[key] = "You are a helpful assistant." # Default system prompt
        else:
            display_settings[key] = None # Or some other default

    # Override with DB values if they exist
    for s in settings:
        display_settings[s.key] = s.value
        if s.key == 'openai_api_key_admin' and s.value: # Obfuscate API key from DB
            display_settings[s.key] = "******** (Set in DB)"


    return jsonify(display_settings), 200

@bp.route('/settings', methods=['POST']) # Using POST for simplicity, could be PUT
@login_required
@admin_required
def update_settings():
    data = request.get_json()
    if not data:
        return jsonify({'message': 'No data provided'}), 400

    allowed_keys = ['llm_model', 'openai_api_key_admin', 'openai_api_base_admin', 'system_prompt']
    updated_settings = []

    for key, value in data.items():
        if key not in allowed_keys:
            current_app.logger.warn(f"Admin tried to set an unknown key: {key}")
            continue # Skip unknown keys or return an error

        setting = SystemSetting.query.filter_by(key=key).first()
        if not setting:
            setting = SystemSetting(key=key)
            db.session.add(setting)
        
        # Special handling for API key to update app config if changed through admin
        if key == 'openai_api_key_admin' and value:
             # Don't store actual key in DB, instead update current_app.config
             # This is a simplification; robust key management is complex.
             # Here, we just use it to signal the app to use this if provided.
             # For this example, let's store it in DB too but be mindful of security.
             # A better way would be to store an encrypted version or reference to a vault.
            current_app.config['OPENAI_API_KEY'] = value 
            setting.value = value # Store in DB too, can be masked when retrieved.
        elif key == 'openai_api_base_admin' and value:
            current_app.config['OPENAI_API_BASE'] = value
            setting.value = value
        else:
            setting.value = str(value) # Ensure it's a string

        updated_settings.append({'key': key, 'value': setting.value if key not in ['openai_api_key_admin'] else "********"})
    
    db.session.commit()
    
    # Invalidate any cached LLM client if settings affecting it changed
    # (This example doesn't have explicit caching for the client instance itself,
    # but if it did, this is where you'd clear it)

    return jsonify({'message': 'Settings updated successfully', 'updated_settings': updated_settings}), 200

# Example: Endpoint to list users (for admin)
@bp.route('/users', methods=['GET'])
@login_required
@admin_required
def list_users():
    users = User.query.all()
    return jsonify([{
        'id': u.id, 
        'username': u.username, 
        'is_admin': u.is_admin
    } for u in users]), 200

# Example: Endpoint to make a user admin (for admin)
@bp.route('/users/<int:user_id>/make-admin', methods=['POST'])
@login_required
@admin_required
def make_admin(user_id):
    user = User.query.get_or_404(user_id)
    if user.is_admin:
        return jsonify({'message': 'User is already an admin'}), 400
    user.is_admin = True
    db.session.commit()
    return jsonify({'message': f'User {user.username} is now an admin'}), 200